﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ReachStats.ReachApiReference;
using System.ComponentModel;
using System.Configuration;

namespace ReachStats
{
    public class ReachAPIResponseArgs<TServiceResponse> : EventArgs
    {
        public TServiceResponse Response { get; set; }

        public ReachAPIResponseArgs(TServiceResponse response)
        {
            Response = response;
        }
    }

    public class ReachAPIErrorArgs : EventArgs
    {
        public Exception Error { get; set; }
    }


    public abstract class BaseReachAPIService<TServiceResponse>
        where TServiceResponse : class
    {
        public const string APIKeyAppSettingName = "HaloReachAPIKey";

        protected ReachApiJsonClient reachClient = new ReachApiJsonClient();
        protected BackgroundWorker serviceWorker = new BackgroundWorker();

        protected string apiKey = string.Empty;

        protected abstract TServiceResponse DoServiceCall();

        public event EventHandler<ReachAPIResponseArgs<TServiceResponse>> GotResponse;
        public event EventHandler<ReachAPIErrorArgs> GotError;

        public BaseReachAPIService()
            : this(ConfigurationManager.AppSettings[APIKeyAppSettingName])
        {

        }

        public BaseReachAPIService(string APIKey)
        {
            if (string.IsNullOrEmpty(APIKey))
                throw new ArgumentNullException("APIKey", String.Format("Check for an AppSetting named {0}", APIKeyAppSettingName));

            apiKey = APIKey;

            serviceWorker.RunWorkerCompleted += serviceWorker_RunWorkerCompleted;
            serviceWorker.DoWork += serviceWorker_DoWork;
        }

        protected void StartServiceCall()
        {
            serviceWorker.RunWorkerAsync();
        }

        void serviceWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                e.Result = DoServiceCall();
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException("Error during service call", ex);
            }
        }

        void serviceWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                HandleServiceError(e.Error);
                return;
            }

            HandleServiceResponse(e.Result as TServiceResponse);
        }

        private void HandleServiceResponse(TServiceResponse response)
        {
            if (GotResponse != null)
                GotResponse(this, new ReachAPIResponseArgs<TServiceResponse>(response));
        }

        private void HandleServiceError(Exception exception)
        {
            if (GotError != null)
                GotError(this, new ReachAPIErrorArgs() { Error = exception });
        }

    }
}
